package com.galaxy.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.galaxy.common.core.domain.R;
import com.galaxy.common.mybatis.core.page.PageQuery;
import com.galaxy.common.mybatis.core.page.TableDataInfo;
import com.galaxy.order.api.RemoteCouponService;
import com.galaxy.order.api.RemoteDeviceService;
import com.galaxy.order.api.RemoteProductService;
import com.galaxy.order.chlients.RabbitMQOrderClient;
import com.galaxy.order.domain.*;
import com.galaxy.order.domain.bo.OrderBo;
import com.galaxy.order.domain.bo.OrderBo1;
import com.galaxy.order.domain.vo.OrderDetailVo;
import com.galaxy.order.domain.vo.OrderVo;
import com.galaxy.order.mapper.*;
import com.galaxy.order.service.OrderService;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单信息Service业务层处理
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final OrderMapper orderMapper;
    private final Converter converter;

    private final OrderDetailMapper orderDetail;

    private final OrderCouponMapper orderCoupon;

    private final OrderStatusLogMapper orderStatusLog;

    @Autowired
    private RemoteDeviceService remoteDeviceService;

    @Autowired
    private RabbitMQOrderClient rabbitMQOrderClient;


    @Autowired
    private RemoteCouponService service;

    @Autowired
    private RemoteProductService remoteProductService;



    @DS("slave")
    @Override
    public TableDataInfo<OrderVo> queryPageList(OrderBo bo, PageQuery pageQuery) {
        Page<Object> build = pageQuery.build();
        Long current = (build.getCurrent()-1)*build.getSize();
        List<OrderVo> list = orderMapper.selectOrderVoList(bo.getOrderNo(), bo.getUserId(), bo.getStatus(), build.getSize(),current);
        Long l = orderMapper.selectCount(buildQueryWrapper(bo));
        TableDataInfo<OrderVo> build1 = TableDataInfo.build(list);
        build1.setTotal(l);
        return build1;
    }

    @DS("slave")
    @Override
    public TableDataInfo<OrderVo> queryPageList1(OrderBo bo, PageQuery pageQuery) {
        Page<OrderVo> list = orderMapper.selectOrderVoList1(bo.getOrderNo(), bo.getUserId(), bo.getStatus(), pageQuery.build());
        return TableDataInfo.build(list);
    }

    @DS("slave")
    @Override
    public List<OrderVo> queryList(OrderBo bo) {
        LambdaQueryWrapper<Order> lqw = buildQueryWrapper(bo);
        List<OrderVo> collect = orderMapper.selectList(lqw).stream()
            .map(order -> converter.convert(order, OrderVo.class))
            .collect(Collectors.toList());
        for(OrderVo orderVo : collect){
            orderVo.setOrderDetail(
                orderDetail.selectVoList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderVo.getDeviceId()))
            );
            orderVo.setOrderCoupon(
                orderCoupon.selectVoById(orderVo.getDeviceId())
            );
        }
        return collect;
    }

    @DS("slave")
    @Override
    public OrderVo queryById(Long id) {
        return orderMapper.selectOrderVoById(id);
    }


    @DS("slave")
    @Override
    public OrderVo queryByOrderNo(String orderNo) {
        OrderVo orderVo = orderMapper.selectOrderVoByOrderNo(orderNo);
        return orderVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Order insertByBo(OrderBo bo) {
        Order add = converter.convert(bo, Order.class);
        if(orderMapper.insert(add) > 0){
            bo.getOrderDetail().forEach(detail -> detail.setOrderId(add.getId()));
            bo.getOrderDetail().forEach(detail -> detail.setOrderNo(add.getOrderNo()));
            List<OrderDetail> convert = converter.convert(bo.getOrderDetail(), OrderDetail.class);
            orderDetail.insertBatch(convert);
            OrderStatusLog add1 = new OrderStatusLog();
            add1.setOrderId(add.getId());
            add1.setOrderNo(add.getOrderNo());
            add1.setStatus(1);
            add1.setStatusDesc("订单创建成功");
            add1.setOperator("user");
            orderStatusLog.insert(add1);
            if(bo.getOrderCoupon() != null){
                OrderCoupon orderCoupon1 = bo.getOrderCoupon();
                orderCoupon1.setOrderId(add.getId());
                orderCoupon1.setOrderNo(add.getOrderNo());
                orderCoupon.insert(orderCoupon1);
            }
            return add;
        }
        return add;
    }


    @Override
    public Boolean updateByBo(OrderBo bo) {
        Order update = converter.convert(bo, Order.class);
        return orderMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo1(OrderBo1 bo) {
        Order update = converter.convert(bo, Order.class);
        orderMapper.updateById(update);
        OrderVo orderVo = orderMapper.selectOrderVoById(bo.getId());
        for(OrderDetailVo orderDetailVo : orderVo.getOrderDetail()){
            remoteProductService.updateSales(orderDetailVo.getProductId(), orderDetailVo.getQuantity());
        }
        for(OrderDetailVo orderDetailVo : orderVo.getOrderDetail()){
            for (int i = 1;i <= orderDetailVo.getQuantity();i++){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("deviceNo", remoteDeviceService.getInfo(orderVo.getDeviceId()).getData());
                jsonObject.put("channelNo", orderDetailVo.getChannelNo());
                jsonObject.put("orderNo", orderDetailVo.getOrderNo());
                rabbitMQOrderClient.sendMessage(jsonObject.toJSONString());
            }

        }

        return orderDetail.update(new LambdaUpdateWrapper<OrderDetail>().set(OrderDetail::getStatus, 1).eq(OrderDetail::getOrderId, bo.getId()))>0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(List<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO: Add validation logic here
        }
//        orderDetail.update(new LambdaUpdateWrapper<OrderDetail>().set(OrderDetail::getStatus, 6).in(OrderDetail::getOrderId, ids));
        List<Order> orders = baseMapper.selectBatchIds(ids);
        orders.forEach(order -> {
            order.setStatus(6);
        });
        return orderMapper.updateBatchById(orders);
    }

    @Override
    public Long getTodayOrderCount() {
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        return baseMapper.selectCount(new LambdaQueryWrapper<Order>()
            .eq(Order::getStatus, 2)
            .ge(Order::getCreateTime, today));
    }

    @Override
    public BigDecimal getTodaySales() {
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        List<Order> orders = baseMapper.selectList(new LambdaQueryWrapper<Order>()
                .eq(Order::getStatus, 2)
            .ge(Order::getCreateTime, today));
        return orders.stream()
            .map(Order::getActualAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    private LambdaQueryWrapper<Order> buildQueryWrapper(OrderBo bo) {
        LambdaQueryWrapper<Order> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getOrderNo() != null, Order::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getUserId() != null, Order::getUserId, bo.getUserId());
        lqw.eq(bo.getStatus() != null, Order::getStatus, bo.getStatus());
        return lqw;
    }

    @Override
    public Boolean orderCancel(String orderNo) {
        OrderVo orderVo = orderMapper.selectOrderVoByOrderNo(orderNo);
        if(orderVo!=null && orderVo.getId()!=null){
            Order order = new Order();
            order.setStatus(4);
            order.setId(orderVo.getId());
            order.setUpdateTime(orderVo.getUpdateTime());
            order.setUpdateBy(orderVo.getUpdateBy());
            order.setCancelTime(LocalDateTime.now());
            order.setCancelReason("自动取消订单");
            boolean b = baseMapper.updateById(order) > 0;

            LambdaQueryWrapper<OrderCoupon> lqw = Wrappers.lambdaQuery();
            lqw.eq(OrderCoupon::getOrderId, orderVo.getId());
            lqw.eq(OrderCoupon::getOrderNo, orderVo.getOrderNo());
            orderCoupon.delete(lqw);

            R<Boolean> update = service.update(orderVo.getOrderNo());
            List<CheckStock> checkStockList = new ArrayList<>();
            for(OrderDetailVo orderDetailBo : orderVo.getOrderDetail()){
                CheckStock checkStock = new CheckStock();
                checkStock.setDeviceId(orderVo.getDeviceId());
                checkStock.setChannelId(Long.parseLong(orderDetailBo.getChannelNo()));
                checkStock.setProductId(orderDetailBo.getProductId());
                checkStock.setStock(orderDetailBo.getQuantity());
                checkStockList.add(checkStock);
            }

            R<Boolean> updateStock = remoteDeviceService.update(checkStockList);
            if (b && update.getData() && updateStock.getData()) {
                log.info("取消成功");
                return true;
            } else {
                log.error("取消失败");
                return false;
            }
        }else {
            log.error("取消失败");
            return false;

        }
    }
}
